/* sys tem init
 *
 */

#ifndef __SYSTEM_INIT_H__
#define __SYSTEM_INIT_H__

#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
#ifndef __CLANG_ARM
#define __CLANG_ARM
#endif
#endif

/* Compiler Related Definitions */
#if defined(__CC_ARM) || defined(__CLANG_ARM) /* ARM Compiler */
#include <stdarg.h>
#define OBJ_SECTION(x) __attribute__((section(x)))
#define OBJ_UNUSED __attribute__((unused))
#define OBJ_USED __attribute__((used))
#define OBJ_ALIGN(n) __attribute__((aligned(n)))
#define OBJ_WEAK __attribute__((weak))
#define OBJ_INLINE static __inline

#elif defined(__IAR_SYSTEMS_ICC__) /* for IAR Compiler */
#include <stdarg.h>
#define OBJ_SECTION(x) @x
#define OBJ_UNUSED
#define OBJ_USED __root
#define PRAGMA(x) _Pragma(#x)
#define OBJ_ALIGN(n) PRAGMA(data_alignment = n)
#define OBJ_WEAK __weak
#define OBJ_INLINE static inline

#elif defined _WIN32
#define OBJ_SECTION(x)
#define OBJ_UNUSED
#define OBJ_USED
#define PRAGMA(x)
#define OBJ_ALIGN(n)
#define OBJ_WEAK
#define OBJ_INLINE
#elif defined(__GNUC__) /* GNU GCC Compiler */
#ifdef RT_USING_NEWLIB
#include <stdarg.h>
#else
/* the version of GNU GCC must be greater than 4.x */
typedef __builtin_va_list __gnuc_va_list;
typedef __gnuc_va_list va_list;
#define va_start(v, l) __builtin_va_start(v, l)
#define va_end(v) __builtin_va_end(v)
#define va_arg(v, l) __builtin_va_arg(v, l)
#endif

#define OBJ_SECTION(x) __attribute__((section(x)))
#define OBJ_UNUSED __attribute__((unused))
#define OBJ_USED __attribute__((used))
#define OBJ_ALIGN(n) __attribute__((aligned(n)))
#define OBJ_WEAK __attribute__((weak))
#define OBJ_INLINE static __inline
#else
#define OBJ_SECTION(x)
#define OBJ_UNUSED
#define OBJ_USED
#define OBJ_ALIGN(n)
#define OBJ_WEAK
#define OBJ_INLINE
#endif

/* initialization export */
typedef void (*sys_init_fn)(void);

#define OBJ_INIT_EXPORT(fn, level) \
    void fn(void);                 \
    OBJ_USED static const sys_init_fn __sys_init_##fn OBJ_SECTION(".sys_obj_fn." level) = fn

/* board init routines will be called in board_init() function */
#define obj_init_order1(fn) OBJ_INIT_EXPORT(fn, "1")
#define obj_init_order2(fn) OBJ_INIT_EXPORT(fn, "2")
#define obj_init_order3(fn) OBJ_INIT_EXPORT(fn, "3")
#define obj_init_order4(fn) OBJ_INIT_EXPORT(fn, "4")
#define obj_init_order5(fn) OBJ_INIT_EXPORT(fn, "5")
#define obj_app_order(fn) OBJ_INIT_EXPORT(fn, "7")

#define INIT_EXPORT_ORIGIN obj_init_order1 // 初始化起点，不依赖于任何其他模块的硬件初始化
#define INIT_EXPORT_PRE obj_init_order2    // 预处理,依赖于基础硬件的系统，比如读取参数
#define INIT_EXPORT_HAL obj_init_order3    // 依赖参数或其他硬件的硬件模块，比如参数可设的串口
#define INIT_EXPORT_SYS obj_init_order4    // 系统级初始化
#define INIT_EXPORT_APP obj_init_order5    // 应用级初始化
#define APP_LIST_EXPORT obj_app_order      // 应用列表

void sys_init(void);
void sys_app_init(void);
void sys_app_run(void);
void sys_app_run_once(void);

#endif
